<?php
//   +----------------------------------------------------------------------
//   | Copyright (c) 2015-2025 http://www.hdphp.cn All rights reserved.
//   | Licensed ( http://www.hdphp.cn/licenses/ )
//   | Author: Jack <sophia2152@qq.com>
//   | 官方网址: http://www.hdphp.cn
//   | 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用。
//   | 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
//   +----------------------------------------------------------------------
namespace app\services\system\admin;

use app\dao\system\admin\SystemAdminDao;
use app\services\BaseServices;
use app\services\system\log\SystemLoginLogServices;
use app\services\system\SystemMenusServices;
use app\services\system\SystemRoleServices;
use hdphp\exceptions\AdminException;
use hdphp\services\CacheService;

/**
 * Class：系统登录服务
 * 创建人：Jack
 * 创建时间：2023/7/29 14:49
 * @package app\services\system\admin
 * @mixin SystemAdminDao
 */
class SystemAdminServices extends BaseServices
{

    /**
     * SystemAdminServices constructor
     * @param SystemAdminDao $dao
     */
    public function __construct(SystemAdminDao $dao)
    {
        $this->dao = $dao;
    }

    /**
     * 注释：登录系统
     * 创建人：Jack
     * 创建时间：2023/7/29 16:31
     * @param string $username
     * @param string $password
     * @param string $type
     * @param bool   $is_mobile
     * @return array
     */
    public function login(string $username, string $password, string $type, bool $is_mobile = false)
    {
        $adminInfo = $this->verifyLogin($username, $password, $is_mobile);
        $tokenInfo = $this->createToken($adminInfo->id, $type, $adminInfo->password);
//        /** @var SystemMenusServices $services */
//        $services = app()->make(SystemMenusServices::class);
//        [$menus, $uniqueAuth] = $services->getMenusList($adminInfo->roles, (int)$adminInfo->level);
        return [
            'token' => $tokenInfo['token'],
            'expires_in' => $tokenInfo['params']['exp'],
            'expires_time' => date('Y-m-d H:i:s', $tokenInfo['params']['exp']),
            //            'menus' => $menus,
            //            'unique_auth' => $uniqueAuth,
            'user_info' => [
                'id' => $adminInfo['id'],
                'tel' => $adminInfo['tel'],
                'face' => $adminInfo['face'],
                'email' => $adminInfo['email'],
                'phone' => $adminInfo['phone'],
                'username' => $adminInfo['username'],
                'true_name' => $adminInfo['true_name'],
                'department' => $adminInfo['department']
            ],
            'version' => get_version()
        ];
    }

    /**
     * 注释：重置管理员密码
     * 创建人：Jack
     * 创建时间：2023/7/30 9:40
     * @param string $phone
     * @param string $new_password
     * @return true
     */
    public function resetPassword(string $phone, string $new_password)
    {
        $adminInfo = $this->dao->phoneByAdmin($phone);
        if ($adminInfo) {
            $factor = substr(random_string('md5'), 0, 6);
            $adminInfo->factor = $factor;
            $adminInfo->password = md5(md5($new_password) . $factor);
            $adminInfo->save();
            return true;
        }
        throw new AdminException('管理员不存在，请检查手机号码');
    }

    /**
     * 注释：系统登录验证
     * 创建人：Jack
     * 创建时间：2023/7/29 7:45 PM
     * @param string $username
     * @param string $password
     * @param bool   $is_mobile
     * @return array|mixed
     */
    private function verifyLogin(string $username, string $password, bool $is_mobile = false)
    {
        $key = 'login_identifying_code_' . $username;
        if ($is_mobile) {
            $adminInfo = $this->dao->phoneByAdmin($username);
        } else {
            $adminInfo = $this->dao->usernameByAdmin($username);
        }
        if (!$adminInfo) {
            throw new AdminException('管理员不存在!');
        }
        /** @var SystemLoginLogServices $systemLoginLogServices */
        $systemLoginLogServices = app()->make(SystemLoginLogServices::class);
        $login_time = $systemLoginLogServices->getCount(['uid' => $adminInfo->id, 'status' => 0, 'time' => 'today', 'timeKey' => 'login_time']);
        if ($login_time > 5) {
            throw new AdminException('login times exceeds limit');
        }
        if (!$adminInfo->status) {
            $systemLoginLogServices->recordLoginLog($adminInfo->id, 0, app('request')->ip());
            throw new AdminException('您已被禁止登录!');
        }
        if (!$is_mobile && md5(md5($password) . $adminInfo->factor) != $adminInfo->password) {
            $systemLoginLogServices->recordLoginLog($adminInfo->id, 0, app('request')->ip());
            throw new AdminException('账号或密码错误，请重新输入');
        }

        $systemLoginLogServices->recordLoginLog($adminInfo->id, 1, app('request')->ip());
        $adminInfo->last_time = time();
        $adminInfo->last_ip = app('request')->ip();
        $adminInfo->login_count++;
        $adminInfo->save();

        return $adminInfo;
    }

    /**
     * 注释：管理员列表
     * 创建人：Jack
     * 创建时间：2023/7/31 11:21
     * @param array $where
     * @return array
     */
    public function getAdminList(array $where)
    {
        [$page, $limit] = $this->getPageValue();
        $list = $this->dao->getList($where, $page, $limit);
        $count = $this->dao->count($where);

        /** @var SystemRoleServices $service */
        $service = app()->make(SystemRoleServices::class);
        $allRole = $service->getRoleArray();
        foreach ($list as &$item) {
            if ($item['roles']) {
                $roles = [];
                foreach ($item['roles'] as $id) {
                    if (isset($allRole[$id])) $roles[] = $allRole[$id];
                }
                if ($roles) {
                    $item['roles_name'] = implode(',', $roles);
                } else {
                    $item['roles_name'] = '';
                }
            }

            $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']);
            $item['_last_time'] = $item['last_time'] ? date('Y-m-d H:i:s', $item['last_time']) : '';
        }

        return compact('list', 'count');
    }

    /**
     * 注释：创建管理员
     * 创建人：Jack
     * 创建时间：2023/7/31 15:17
     * @param array $data
     * @return mixed
     */
    public function create(array $data)
    {
        if ($data['conf_password'] != $data['password']) {
            throw new AdminException('两次输入的密码不相同');
        }
        unset($data['conf_password']);
        if ($data['username']) {
            $username = strip_tags($data['username']);
            if ($this->dao->be(['username' => $username])) {
                $data['username'] = 'hd_' . $username . '_' . rand(1, 99);
            } else {
                $data['username'] = strip_tags($data['username']);
            }
        } else {
            // 生成用户账号
            $data['username'] = 'hd_' . substr($data['phone'], -4) . '_' . rand(1, 99);
        }
        if ($this->dao->count(['username' => $data['username'], 'is_delete' => 0])) {
            throw new AdminException('管理员账号已存在');
        }
        if ($this->dao->count(['phone' => $data['phone'], 'is_delete' => 0])) {
            throw new AdminException('管理员电话已存在');
        }
        if ($data['email'] && !check_mail($data['email'])) {
            throw new AdminException('邮箱格式错误');
        }
        $data['roles'] = implode(',', $data['roles']);
        $factor = substr(random_string('md5'), 0, 6);
        $data['factor'] = $factor;
        $data['password'] = md5(md5($data['password']) . $factor);
        $data['add_ip'] = request()->ip();
        $data['add_time'] = time();

        return $this->transaction(function () use ($data) {
            if ($this->dao->save($data)) {
                \hdphp\services\CacheService::clear();
                return true;
            } else {
                throw new AdminException('添加失败');
            }
        });
    }

    /**
     * 注释：修改管理员
     * 创建人：Jack
     * 创建时间：2023/8/1 8:55
     * @param int   $id
     * @param array $data
     * @return bool
     */
    public function save(int $id, array $data)
    {
        if (!$adminInfo = $this->dao->get($id)) {
            throw new AdminException('管理员不存在,无法修改');
        }
        if ($adminInfo->is_delete) {
            throw new AdminException('管理员已经删除');
        }
        // 修改密码
        if (isset($data['password']) && $data['password']) {
            if (!$data['conf_password']) {
                throw new AdminException('请输入确认密码');
            }
            if ($data['conf_password'] != $data['password']) {
                throw new AdminException('上次输入的密码不相同');
            }
            $factor = substr(random_string('md5'), 0, 6);
            $adminInfo->factor = $factor;
            $adminInfo->password = md5(md5($data['password']) . $factor);
        }
        // 修改账号
        if (isset($data['username']) && $data['username'] != $adminInfo->username && $this->dao->isUsernameUsable($data['username'], $id)) {
            throw new AdminException('管理员账号已存在');
        }
        if (isset($data['phone']) && $data['phone'] != $adminInfo->phone && $this->dao->count(['phone' => $data['phone'], 'is_delete' => 0])) {
            throw new AdminException('管理员电话已存在');
        }
        if (isset($data['roles'])) {
            $adminInfo->roles = implode(',', $data['roles']);
        }

        $adminInfo->true_name = $data['true_name'] ?? $adminInfo->true_name;
        $adminInfo->phone = $data['phone'] ?? $adminInfo->phone;
        $adminInfo->username = $data['username'] ?? $adminInfo->username;
        $adminInfo->face = $data['face'] ?? $adminInfo->face;
        $adminInfo->tel = $data['tel'] ?? $adminInfo->tel;
        $adminInfo->email = $data['email'] ?? $adminInfo->email;
        $adminInfo->department = $data['face'] ?? $adminInfo->department;
        $adminInfo->status = $data['status'];
        if ($adminInfo->save()) {
            \hdphp\services\CacheService::clear();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 注释：修改当前管理员信息
     * 创建人：Jack
     * 创建时间：2023/7/31 14:37
     * @param int   $id
     * @param array $data
     * @return bool
     */
    public function updateAdmin(int $id, array $data)
    {
        $adminInfo = $this->dao->get($id);
        if (!$adminInfo)
            throw new AdminException('管理员信息未查到');
        if ($adminInfo->is_delete) {
            throw new AdminException('管理员已经删除');
        }
        if ($data['face'] != '') {
            $adminInfo->face = $data['face'];
        } else if ($data['true_name'] != '') {
            $adminInfo->true_name = $data['true_name'];
        } else if ($data['password'] != '') {
            if (md5(md5($data['password']) . $adminInfo->factor) != $adminInfo->password) {
                throw new AdminException('原始密码错误');
            }
            if (!$data['new_password']) {
                throw new AdminException('请输入新密码');
            }
            if (!$data['conf_password']) {
                throw new AdminException('请输入确认密码');
            }
            if ($data['new_password'] != $data['conf_password']) {
                throw new AdminException('两次输入的密码不一致');
            }
            $factor = substr(random_string('md5'), 0, 6);
            $adminInfo->factor = $factor;
            $adminInfo->password = md5(md5($data['new_password']) . $factor);
        } else if ($data['phone'] != '') {
            $verifyCode = CacheService::get('code_' . $data['phone']);
            if (!$verifyCode) {
                throw new AdminException('请先获取验证码');
            }
            $verifyCode = substr($verifyCode, 0, 6);
            if ($verifyCode != $data['code']) {
                CacheService::delete('code_' . $data['phone']);
                throw new AdminException('验证码错误');
            }
            $adminInfo->phone = $data['phone'];
        }
        if ($adminInfo->save()) {
            return true;
        }
        return false;
    }

    
    public function getMenusList(array $roles, int $level = 0)
    {
        /** @var SystemMenusServices $services */
        $services = app()->make(SystemMenusServices::class);
        [$menus, $uniqueAuth] = $services->getMenusList($roles, $level);
        return $menus;
    }

}